'''
goparse.py

Parser for the Gene Ontology Mapping format

Usage: 
$ python goparse.py <mapping_url>

Ex:
python goparse.py http://www.geneontology.org/external2go/ec2go
or 
python goparse.py urls

The latter form just prints the urls for the mapping files from the GO website

Mappings:
http://www.geneontology.org/external2go/

File format:
http://www.geneontology.org/GO.format.shtml#mappings

A mapping file is a sequence of records of the form

  external_database:term_identifier > GO:GO_term_name ; GO:id

'''

import urllib as u
import sys
import re

DELIM = "\t"

class EmptyGOId(ValueError):
  pass 
class ParseError(ValueError):
  pass 

expr = re.compile("(.*?):(.*?)\s*>\s*(.*?)\s*;\s*(.*)\s*")
empty= re.compile("(.*?):(.*?)\s*>\s*(GO:.*?)\.")

def parsegoline(line):
  m = expr.match(line)
  if m: return m.groups()
  else: 
    if empty.match(line):
      raise EmptyGOId("Empty GO Id: %s" % line)
    else:
      raise ValueError("Parse error: %s" % line)

def goparse(url):
  f = u.urlopen(url)
  print "db" + DELIM + "dbid" + DELIM + "goterm" + DELIM + "goid"
  for line in f:
    line = line.strip()
    if line[0] != '!':
      try:
        record = parsegoline(line)

        # print a delimited record 
        print DELIM.join(record)
      except EmptyGOId:
        pass # ignore these errors
      except ValueError, e:
        # report all other errors, but keep going
        print >> sys.stderr, e

def parseargs():
  if len(sys.argv) < 2:
    printUsage()
  return sys.argv[1]

if __name__ == '__main__':
  goparse(parseargs())

